from selenium import webdriver
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
from selenium.webdriver.common.by import By
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.keys import Keys
from lxml import etree
import re
import time
import json

area_itm = {
    '北京': (1, 0),
    '广州': (19, 1),
    '深圳': (19, 3),
    '上海': (9, 0),
    '成都': (23, 1),
    '重庆': (22, 0),
    '杭州': (11, 1),
    '武汉': (17, 1),
    '西安': (27, 1),
    '南京': (10, 1),
    '长沙': (18, 1),
    '东莞': (19, 17),
}


class AutoSpider(object):

    def __init__(self) -> None:
        options = webdriver.FirefoxOptions()
        options.add_argument("disable-blink-features=AutomationControlled")  # 去掉webdriver痕迹
        # options.add_argument("--headless")  # 配置无头模式
        desired_capabilities = DesiredCapabilities.FIREFOX
        desired_capabilities['loggingPrefs'] = {'performance': 'ALL'}
        # binary = FirefoxBinary('/opt/apps/firefox/files/firefox')
        self.browser = webdriver.Firefox(
            executable_path='./geckodriver.exe',
            # firefox_binary=binary,
            options=options,
            desired_capabilities=desired_capabilities)
        self.browser.maximize_window()
        self.wait = WebDriverWait(self.browser, 20)  # 等待20s后抛出异常
        self.first_click = True
        self.result = {}

    def search_year_condition(self, left_times):
        # 联系电话
        have_tel_btn = self.wait.until(EC.element_to_be_clickable((By.XPATH, '//span[contains(text(), "有联系电话")]')))
        have_tel_btn.click()

        # 企业类型
        for enterprise_type in ['有限责任公司', '股份有限公司', '国有企业', '外商投资企业']:
            self.wait.until(EC.element_to_be_clickable((By.XPATH, '//span[contains(text(), "{}")]'.format(enterprise_type)))).click()

        # 成立年限
        time_btn = self.wait.until(EC.element_to_be_clickable((By.XPATH, '//div[contains(@class, "ant-picker-input")]')))
        self.click_time_btn(time_btn, left_times)

    def click_time_btn(self, start_time_btn, left_times):
        start_time_btn.click()
        time.sleep(2)
        # 开始时间（如：2022-01-01）
        for i in range(left_times):
            self.wait.until(EC.element_to_be_clickable((By.XPATH, '//span[@class="ant-picker-super-prev-icon"]'))).click()

        start_month_btn = self.wait.until(EC.element_to_be_clickable((By.XPATH, '//div[@class="ant-picker-panels"]/div[1]//button[@class="ant-picker-month-btn"]')))
        start_month_btn.click()
        # 1月
        month_one_btn = self.wait.until(EC.element_to_be_clickable((By.XPATH, '//div[text()="1月"]')))
        month_one_btn.click()
        # 1日
        day_one_btn = self.wait.until(EC.element_to_be_clickable((By.XPATH, '//td[contains(@title, "-01-01")]/div')))
        day_one_btn.click()

        # 结束时间（如：2023-01-01）
        if not self.first_click:
            for i in range(left_times+1):
                self.wait.until(EC.element_to_be_clickable((By.XPATH, '//span[@class="ant-picker-super-prev-icon"]'))).click()
        self.first_click = False
        start_month_btn = self.wait.until(EC.element_to_be_clickable((By.XPATH, '//div[@class="ant-picker-panels"]/div[2]//button[@class="ant-picker-month-btn"]')))
        start_month_btn.click()
        # 12月
        month_one_btn = self.wait.until(EC.element_to_be_clickable((By.XPATH, '//div[text()="12月"]')))
        month_one_btn.click()
        # 1日
        day_one_btn = self.wait.until(EC.element_to_be_clickable((By.XPATH, '//td[contains(@title, "-01-01")]/div')))
        day_one_btn.click()
        # 时间确定
        ensure_btn = self.wait.until(EC.element_to_be_clickable((By.XPATH, '//button[@class="ant-btn ant-btn-primary ant-btn-sm customer-condition-button"]')))
        ensure_btn.click()

    def search_area_condition(self, itm):
        # 地区：[北京、广州、深圳、上海、成都、重庆、杭州、武汉、西安、南京、长沙、东莞]
        try:
            area_btn = self.wait.until(EC.element_to_be_clickable((By.XPATH, '//span[text()="省份地区"]/parent::div//span[@class="ant-select-selection-search"]')))
            area_btn.click()
        except Exception:
            pass

        input_btn = self.browser.find_element(By.XPATH, '//span[text()="省份地区"]/parent::div//span[@class="ant-select-selection-search"]/input')
        for i in range(itm[0]):
            input_btn.send_keys(Keys.DOWN)
        input_btn.send_keys(Keys.RIGHT)
        for i in range(itm[1]):
            input_btn.send_keys(Keys.DOWN)
        input_btn.send_keys(Keys.RIGHT)
        input_btn.send_keys(Keys.ENTER)

        # 检索
        search_btn = self.wait.until(EC.element_to_be_clickable((By.XPATH, '//button[contains(./span/text(), "检 索")]')))
        search_btn.click()

    def download_page_source(self, area):
        # 翻2页，下载公司详情页
        for i in range(1, 3):
            page_btn = self.wait.until(EC.element_to_be_clickable((By.XPATH, '//li[@title="{}"]'.format(i))))
            page_btn.click()
            time.sleep(2)
            curr_window = self.browser.current_window_handle  # 获取当前主页面
            company_ls = self.browser.find_elements(By.XPATH, '//div[@class="title-wrapper"]/h2')
            for company in company_ls:
                company.click()
                windows = self.browser.window_handles  # 获取当前所有页面
                self.browser.switch_to.window(windows[1])  # 切换到新页面
                time.sleep(2)
                # 展开更多电话
                try:
                    more_btn_ls = self.browser.find_elements(By.XPATH, '//span[@class="more-icon"]')
                    for more_btn in more_btn_ls:
                        more_btn.click()
                except Exception:
                    # print('只有一个电话，没有【展开】按钮')
                    pass
                page_url = self.browser.find_element(By.XPATH, '//link[@rel="canonical"]').get_attribute('href')
                if page_url:
                    # company_id = page_url.split('/')[-1]
                    # file_name = './钉钉企典/{}.html'.format(company_id)
                    # with open(file_name, 'w+') as f:
                    #     f.write(self.browser.page_source)
                    #     self.parse_page_source(self.browser.page_source, area)
                    self.parse_page_source(self.browser.page_source, area)
                self.browser.close()
                self.browser.switch_to.window(curr_window)  # 切换指定主页面

    def parse_page_source(self, text, city):
        # 解析网页，获取内容
        # result = {}
        selector = etree.HTML(text, parser=etree.HTMLParser(encoding='utf-8'))

        enterprise_name_xp = selector.xpath('//div[@class="title-wrapper"]/h2/div/text()')
        if enterprise_name_xp:
            ent_name = enterprise_name_xp[0].strip()
            self.result[ent_name] = {}

            page_url = ''
            page_url_xp = selector.xpath('//link[@rel="canonical"]/@href')
            if page_url_xp:
                page_url = page_url_xp[0]

            register_time_re = re.findall(r'<li>成立时间：(\d+-\d+-\d+)</li>', text, re.S)
            if register_time_re:
                self.result[ent_name]["start_year"] = register_time_re[0].split('-')[0]

            phone_ls = []
            phone_xp = selector.xpath('//span[contains(text(), "电话")]/parent::li//div[@class="show-more-content-list"]/div/text()')
            if phone_xp:
                for phone in phone_xp:
                    if phone and '(' in phone:
                        phone = phone.replace('(', '').replace(')', '-')
                    phone_ls.append({
                        'phone': phone,
                        'source_ls': ['企典'],
                        'source_href_ls': [page_url]
                    })
            if phone_ls:
                self.result[ent_name]['phone_ls'] = phone_ls
                self.result[ent_name]['phone_count'] = len(phone_ls)

    def main(self):
        self.browser.get('https://www.dingtalk.com/qidian/customer')
        year = 0
        # 搜索条件
        for i in range(25):  # 第一次是0，以后每次减少1年
            self.search_year_condition(year)
            year = 1
            for area, itm in area_itm.items():  # 地区
                time.sleep(2)
                self.search_area_condition(itm)
                # 保存内容
                self.download_page_source(area)
                # 返回
                self.wait.until(EC.element_to_be_clickable((By.XPATH, '//span[contains(text(), "返 回")]'))).click()
                # 清空地区条件
                self.wait.until(EC.element_to_be_clickable((By.XPATH, '//div[contains(text(), "省份地区")]/span'))).click()

        with open('result_qd.json', 'w', encoding='utf-8') as f:
            json.dump(self.result, f, ensure_ascii=False, indent=4)
        self.browser.close()


if __name__ == '__main__':
    spider = AutoSpider()
    spider.main()

    ans = {
        "上海雅辉实业有限公司": {
            "phone_ls": [{
                "phone": "13738728693",
                "source_ls": ["环球贸易网"],
                "source_href_ls": ["http://www.herostart.com/gongsi/fangyuan567.html"]
            }],
            "start_year": 2022,
            "phone_count": 1
        },
        "北京智峰明道餐饮管理有限公司": {
            "start_year": "2022",
            "phone_ls": [
                {
                    "phone": "15501156543",
                    "source_ls": [
                        "企典"
                    ],
                    "source_href_ls": [
                        "http://www.dingtalk.com/qidian/company/1220113000090915363"
                    ]
                }
            ],
            "phone_count": 1
        }
    }
